package com.xcity.game.battle.pve;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.xcity.db.entity.Player;
import com.xcity.game.battle.pve.template.StagePageTemplate;
import com.xcity.game.battle.pve.template.StageTemplate;
import com.xcity.game.common.MessageConst;

import gnu.trove.map.hash.TIntObjectHashMap;
import naga.x.App;
import naga.x.game.template.TemplateService;

public class PVEManager {

	protected Player owner;
	protected List<PVEStage> stages;
	protected PVEStarBoxInfo starBox;
	
	protected TIntObjectHashMap<List<PVEStage>> normalStages;
	protected TIntObjectHashMap<List<PVEStage>> heroStages;//key:templage.page value:List<stage>
	
	public static int STAGE_TYPE_NORMAL = 0;
	public static int STAGE_TYPE_BOSS = 1;
	public static int STAGE_TYPE_HERO = 2;
	
	protected int normalCount;
	protected int heroCount;
	
	public PVEManager(Player owner, List<PVEStage> stages, PVEStarBoxInfo boxinfo) {
		this.owner = owner;
		this.stages = stages != null ? stages : new ArrayList<PVEStage>();
		this.starBox = boxinfo != null? boxinfo : new PVEStarBoxInfo(StageTemplate.MAX_NORMAL_PAGE);
		
		heroStages = new TIntObjectHashMap<List<PVEStage>>();
		normalStages = new TIntObjectHashMap<List<PVEStage>>();
		normalCount = 0;
		heroCount = 0;
		for(int i = 0;i < this.stages.size(); i++){
			PVEStage stage = this.stages.get(i);
			if(stage.getTemplate().getType() == STAGE_TYPE_NORMAL || stage.getTemplate().getType() == STAGE_TYPE_BOSS){
				List<PVEStage> list = normalStages.get(stage.getTemplate().getPage());
				if(list == null){
					list = new ArrayList<PVEStage>();
					normalStages.put(stage.getTemplate().getPage(), list);
				}
				list.add(stage);
				stage.setSubIndex(list.size() - 1);
				normalCount++;
			}else if(stage.getTemplate().getType() == STAGE_TYPE_HERO){
				List<PVEStage> list = heroStages.get(stage.getTemplate().getPage());
				if(list == null){
					list = new ArrayList<PVEStage>();
					heroStages.put(stage.getTemplate().getPage(), list);
				}
				list.add(stage);
				stage.setSubIndex(list.size() - 1);
				heroCount++;
			}
		}
	}

	public Player getOwner() {
		return owner;
	}

	public void setOwner(Player owner) {
		this.owner = owner;
	}
	
	public PVEStage getStage(int id) {
		List<PVEStage> list = stages;
		int size = list.size();
		int midId = StageTemplate.MIN_ID + (size >> 1); // try find faster
		if (id < midId) {
			for (int i = 0; i < size; i++) {
				PVEStage stage = list.get(i);
				if (stage.getId() == id) {
					return stage;
				}
			}
		} else {
			for (int i = size - 1; i >= 0; i--) {
				PVEStage stage = list.get(i);
				if (stage.getId() == id) {
					return stage;
				}
			}
		}
		return null;
	}
	
	/**
	 * 获得关卡列表
	 * @param page 哪一大关 从0开始
	 * @param type 0普通关 1精英关
	 * @return
	 */
	public List<PVEStage> getStages(int page, int type) {
		List<PVEStage> restStages = null;
		if(type == 0){
//			int offset = page * PVEService.NUM_OF_PER_PAGE;
//			if (offset < 0 || offset >= stages.size()) {
//				offset = 0;
//			}
//			restStages = stages.subList(offset, offset + PVEService.NUM_OF_PER_PAGE);
			restStages = normalStages.get(page + 1);
		}else{
			restStages = heroStages.get(page + 1);
		}
		return restStages;
	}
	/**
	 * @param type 0:普通 1:精英
	 */
	public int getCurrentPage(byte type) {
//		return getCurrentNormalIndex() / PVEService.NUM_OF_PER_PAGE;
		return stages.get(getCurrentIndex((byte) type)).getTemplate().getPage() - 1;
	}
	
	/**
	 * 获取当前已通关的最大关卡索引
	 * @param type 0普通关 1精英关
	 * @return
	 */
	public int getCurrentIndex(byte type) {
		List<PVEStage> list = stages;//stages;
		int start = 0;
		int end = normalCount - 1;
		if(type == 1){
			start = normalCount;
			end = normalCount + heroCount - 1;
		}
		int index = start;
		while (start <= end) {
			int mid = (start + end) / 2;
			PVEStage stage = list.get(mid);
			if (stage.isPass()) { // 已通关
				start = mid + 1;
				index = mid;
			} else {
				end = mid - 1;
			}
		}
		return index;
	}
	
	/**
	 * 获得若干关的总星数
	 */
	public int getStagesStar(List<PVEStage> stages){
		int star = 0;
		for(int i = 0;i < stages.size(); i++){
			star = star + stages.get(i).getStar();
		}
		return star;
	}
	
	/**
	 * 对应 page领取的星数宝箱状态
	 * @param page 从0开始
	 * @param type 0普通关 1英雄关
	 * @return
	 */
	public int getStarBoxStateByPage(int page, int type){
		int state = 0;
		if(type == 0){
			int[] states = starBox.getGotNormalBoxState();
			if(page > -1 && page < states.length){
				state = states[page];
			}
		}else{
			int[] counts = starBox.getGotHeroBoxState();
			if(page > -1 && page < counts.length){
				state = counts[page];
			}
		}
		return state;
	}
	
	/**
	 * 星数宝箱ID
	 * @param page 0开始
	 * @param type 0~1
	 * @param phase 0~3
	 * @return
	 */
	public int getStarBoxId(int page, int type, int phase){
		int ret = -1;
		StagePageTemplate pageTemp = App.getApp().getServiceManager().get(TemplateService.class).get(StagePageTemplate.class, page + 1);
		if(pageTemp != null){
			int index = phase + type * StagePageTemplate.MAX_BOX_COUNT;
			if(index > -1 && index < pageTemp.getStarBoxId().length){
				if(pageTemp.getStarBoxId()[index] > 0){
					return pageTemp.getStarBoxId()[index];
				}
			}
		}
		return ret;
	}
	
	/**
	 * 是否领取过星数宝箱
	 * @param page 0~page
	 * @param type 0~1
	 * @param phase 0~2
	 * @return
	 */
	public boolean isGotStarBox(int page, int type, int phase){
		boolean ret = false;
		int state = getStarBoxStateByPage(page, type);
		if((state & (1 << phase)) > 0){
			ret = true;
		}
		return ret;
	}

	/**
	 * 设置已领取
	 * @param page 0~page
	 * @param type 0~1
	 * @param phase 0~2
	 * @return
	 */
	public int setGotStarBox(int page, int type, int phase){
		int[] states;
		if(type == 0){
			states = starBox.getGotNormalBoxState();
		}else{
			states = starBox.getGotHeroBoxState();
		}
		states[page] = states[page] | (1 << phase);
		return states[page];
	}
	
	public int getStarBoxLength(){
		return this.starBox != null? this.starBox.getGotNormalBoxState().length : 0;
	}
	/**
	 * 几关几阶需要多少星
	 * @param page	从0开始
	 * @param phase	从0开始 0~2
	 * @param type	0普通 1精英
	 * @return
	 */
	public int getNeedStarByPhase(int page, int phase, int type){
		StagePageTemplate pageTemp = App.getApp().getServiceManager().get(TemplateService.class).get(StagePageTemplate.class, page + 1);
		return pageTemp.getNeedStar()[phase + type * StagePageTemplate.MAX_BOX_COUNT];
	}
	
	public List<PVEStage> getStages() {
		return stages;
	}
	
	public void resetStarBox(int normalPageCount) {
		this.starBox.reset(normalPageCount);
	}
	
	public void init(List<StageTemplate> templates) {
		List<PVEStage> newer = new ArrayList<PVEStage>(templates.size());
		for (int i = 0; i < stages.size(); i++) {
			PVEStage stage = stages.get(i);
			if (stage.getTemplate() != null) { // 配置表可能删掉了模板
				newer.add(stage);
			}
		}
		boolean first = newer.isEmpty();
		for (int i = 0, size = templates.size(); i < size; i++) {
			StageTemplate template = templates.get(i);
			if (first || getStage(template.getId()) == null) {
				newer.add(new PVEStage(template));
			}
		}
		this.stages = newer;
		

		normalCount = 0;
		heroCount = 0;
		heroStages = new TIntObjectHashMap<List<PVEStage>>();
		for(int i = 0;i < stages.size(); i++){
			PVEStage stage = stages.get(i);
			if(stage.getTemplate().getType() == STAGE_TYPE_NORMAL || stage.getTemplate().getType() == STAGE_TYPE_BOSS){
				List<PVEStage> list = normalStages.get(stage.getTemplate().getPage());
				if(list == null){
					list = new ArrayList<PVEStage>();
					normalStages.put(stage.getTemplate().getPage(), list);
				}
				list.add(stage);
				normalCount++;
				stage.setSubIndex(list.size() - 1);
			}else if(stage.getTemplate().getType() == STAGE_TYPE_HERO){
				List<PVEStage> list = heroStages.get(stage.getTemplate().getPage());
				if(list == null){
					list = new ArrayList<PVEStage>();
					heroStages.put(stage.getTemplate().getPage(), list);
				}
				list.add(stage);
				stage.setSubIndex(list.size() - 1);
				heroCount++;
			}
		}
	}

	/**
	 * 解锁状态 0未解锁 1解锁
	 * @return
	 */
	public byte getLockStateByStage(PVEStage stage){
		byte state = 0;
		if(this.owner.getLevel() >= stage.getTemplate().getLevelLimit()){
			String retStr = proviousName(stage);
			if(retStr == null){
				state = 1;
			}else{
				state = 0;
			}
		}
		return state;
	}
	
	/**
	 * @return 返回需要打的前置关卡名
	 */
	public String proviousName(PVEStage stage){
		if(stage.getTemplate().getType() == STAGE_TYPE_HERO){
			int page = stage.getTemplate().getPage() - 1;
			List<PVEStage> list;
//			//当页第最后一关普通关
//			List<PVEStage> list = getStages(page, 0);
//			if(!list.get(list.size() - 1).isPass()){
//				return list.get(list.size() - 1).getTemplate().getName();
//			}
			PVEStage previous = getStage(stage.getTemplate().getPreviousStage());
			if(previous != null){
				if(!previous.isPass()){
					return previous.getTemplate().getName();
				}
			}
			int curIndex = stage.getSubIndex();
			if(curIndex > 0){
				list = getStages(page, 1);
				if(!list.get(curIndex - 1).isPass()){
					return MessageFormat.format(MessageConst.PVE_PREVIOUS_STAGE_NOT_PASS_NAME_MAIN,  list.get(list.size() - 1).getTemplate().getName());
				}
			}
		}else{
			PVEStage previous = findPreviousStage(stage);
			return previous != null && !previous.isPass() ? previous.getTemplate().getName() : null;
		}
		return null;
	}
	
	/**
	 * 星数宝箱置成没领状态
	 */
	public void resetStarBox(){
		if(starBox != null){
			int len = starBox.getGotHeroBoxState().length;
			for(int i = 0; i < len; i++){
				starBox.getGotHeroBoxState()[i] = 0;
			}
			len = starBox.getGotNormalBoxState().length;
			for(int i = 0; i < len; i++){
				starBox.getGotNormalBoxState()[i] = 0;
			}
		}
	}
	
	/**
	 * 查找当前关卡的前置关卡
	 * @param current
	 * @return
	 */
	public PVEStage findPreviousStage(PVEStage current) {
		TIntObjectHashMap<List<PVEStage>> stageMapping = current.getTemplate().getType() == STAGE_TYPE_HERO ? heroStages : normalStages;
		int page = current.getTemplate().getPage();
		List<PVEStage> list = stageMapping.get(page);
		if (current.getId() == list.get(0).getId()) { // 若当前关卡为该大图中的第一关，则往前推一张图
			list = stageMapping.get(page - 1);
			return list != null ? list.get(list.size() - 1) : null/*当前关卡为第一张图的第一关*/;
		}
		for (int i = list.size() - 1; i >= 0; i--) {
			PVEStage stage = list.get(i);
			if (stage.getId() == current.getId()) {
				return list.get(i - 1); // i - 1 must be >= 0
			}
		}
		return null; // not impossible
	}
	
	/**
	 * 查找当前关卡的下一关卡
	 * @param current
	 * @return
	 */
	public PVEStage findNextStage(PVEStage current) {
		TIntObjectHashMap<List<PVEStage>> stageMapping = current.getTemplate().getType() == STAGE_TYPE_HERO ? heroStages : normalStages;
		int page = current.getTemplate().getPage();
		List<PVEStage> list = stageMapping.get(page);
		if (current.getId() == list.get(list.size() - 1).getId()) { // 若当前关卡为该大图中的最后一关，则往后推一张图
			list = stageMapping.get(page + 1);
			return list != null ? list.get(0) : null/*当前关卡为最后一张图的最后一关*/;
		}
		for (int i = 0; i < list.size(); i++) {
			PVEStage stage = list.get(i);
			if (stage.getId() == current.getId()) {
				return list.get(i + 1); // i + 1 must be < list.size()
			}
		}
		return null; // not impossible
	}

	@Override
	public String toString() {
		return JSON.toJSONString(stages) + ";" + JSON.toJSONString(starBox);
	}
	
}
